import { Injectable, Logger } from '@nestjs/common';
import { DataSource, EntityManager } from 'typeorm';
import {
  OrderListResponse,
  OrderDetailResponse,
} from './reponse/order-response';
import { TbOrder } from '../entities/TbOrder';
import { TbUserAssets } from '../entities/TbUserAssets';
import { OrderModel } from '../models/order-model';
import { UserAssetsModel } from '../models/user-assets-model';
import { SaveOrderDto } from './dto/order.dto';
import { generateOrderNumber } from '../helpers/utils';

@Injectable()
export class OrderService {
  private readonly logger = new Logger(OrderService.name); // 实例化日志

  constructor(
    private readonly orderModel: OrderModel,
    private readonly userAssetsModel: UserAssetsModel,
    private readonly dataSource: DataSource,
  ) {}

  async getOrderList(
    userAddress: string,
    orderNo: string,
    sellerAddress: string,
    assetAddress: string,
    assetType: number,
    limit: number,
    offset: number,
  ): Promise<[OrderListResponse, number]> {
    const [tmpList, count] = await this.orderModel.getOrderList(
      userAddress,
      orderNo,
      sellerAddress,
      assetAddress,
      assetType,
      limit,
      offset,
    );
    const list = new OrderListResponse(tmpList);
    return [list, count];
  }

  async getOrderDetail(id: number): Promise<OrderDetailResponse> {
    const detail = await this.orderModel.getOrderById(id);
    return new OrderDetailResponse(detail);
  }

  async saveOrder(data: SaveOrderDto): Promise<TbOrder> {
    this.logger.log('保存订单日志', data);

    let orderData = new TbOrder();

    if (data.id > 0) {
      orderData.id = data.id;
    } else {
      orderData.orderNo = generateOrderNumber();
    }
    orderData.userId = data.user_id;
    orderData.userAddress = data.user_address;
    orderData.sellerAddress = data.seller_address;
    orderData.assetAddress = data.asset_address;
    orderData.assetType = data.asset_type;
    orderData.tokenId = data.token_id;
    orderData.amount = data.amount;
    orderData.payAmount = data.pay_amount.toString();

    let userAssetsData = await this.userAssetsModel.searchUserAssets(
      data.user_id,
      data.asset_address,
      data.asset_type,
      data.token_id,
    );
    if (userAssetsData.id > 0) {
      userAssetsData.amount += data.amount;
    } else {
      userAssetsData.amount = data.amount;
    }

    userAssetsData.userId = data.user_id;
    userAssetsData.assetAddress = data.asset_address;
    userAssetsData.assetType = data.asset_type;
    userAssetsData.tokenId = data.token_id;

    // 开启事务
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();

    try {
      orderData = await this.orderModel.saveOrder(
        orderData,
        queryRunner.manager,
      );
      await this.userAssetsModel.saveUserAssets(
        userAssetsData,
        queryRunner.manager,
      );

      await queryRunner.commitTransaction(); // 提交事务
    } catch (error) {
      await queryRunner.rollbackTransaction(); // 回滚事务
      throw error;
    } finally {
      await queryRunner.release();
    }
    return orderData;
  }

  async removeOrder(id: number): Promise<void> {
    await this.orderModel.removeOrder(id);
  }
}
